package de.school.cbs.cube;
import java.awt.event.*;
import java.util.*;
import java.awt.Color;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.behaviors.keyboard.KeyNavigatorBehavior;
import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
import com.sun.j3d.utils.behaviors.mouse.MouseTranslate;
import com.sun.j3d.utils.behaviors.mouse.MouseZoom;
import com.sun.j3d.utils.universe.SimpleUniverse;

public class LedCube extends Observable {
    private BranchGroup bg;
    private int width, depth, height;
    private float size;
    private SimpleUniverse universe;
    private LedLayer[] layers;
    private TransformGroup tg;
    private static final List<Color> colors = Arrays.asList(
        Color.GREEN, Color.WHITE, Color.BLUE, Color.RED, Color.YELLOW
    );
    private int selectedColor;

    public LedCube() {
        this(5, 5, 10, 0.1f);
    }

    public LedCube(int width, int depth, int height, float size) {
        this.width = width;
        this.depth = depth;
        this.height = height;
        this.size = size;
        this.selectedColor = 0;

        this.layers = new LedLayer[height];
        this.universe = new SimpleUniverse();
        this.bg = new BranchGroup();
        this.tg = new TransformGroup();
        this.bg.addChild(this.tg);
        this.tg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
        this.tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);

        for(int i = 0; i < height; i++) {
            LedLayer layer = new LedLayer(i, depth, width, size, this.tg, this, this.getColor());
            layer.setPos(i);
            this.layers[i] = layer;
        }
        this.universe.getViewingPlatform().setNominalViewingTransform();

        // Mitte ermitteln
        //System.out.println("X / Y / Z = " + (depth/2) + " / " + (height/2) + " / " + (width/2));
        
        //BoundingSphere boundingSphere = new BoundingSphere(new Point3d(depth/2,height/2,width/2),100);
        BoundingBox boundingSphere = new BoundingBox(new Point3d(0, 0, 0), new Point3d(depth, height, width));

        // Rotate with left mouse
        MouseRotate mouseRotate = new MouseRotate();
        mouseRotate.setTransformGroup(this.tg);
        mouseRotate.setSchedulingBounds(boundingSphere);
        this.bg.addChild(mouseRotate);

        // Moving with right click
        MouseTranslate mouseTranslate = new MouseTranslate();
        mouseTranslate.setTransformGroup(this.tg);
        mouseTranslate.setSchedulingBounds(boundingSphere);
        this.bg.addChild(mouseTranslate);

        // Zoom with middle click
        MouseZoom mouseZoom = new  MouseZoom();
        mouseZoom.setTransformGroup(this.tg);
        mouseZoom.setSchedulingBounds(boundingSphere);
        this.bg.addChild(mouseZoom);

        KeyNavigatorBehavior keyNavigatorBehavior = new KeyNavigatorBehavior(this.tg);
        keyNavigatorBehavior.setSchedulingBounds(boundingSphere);
        this.bg.addChild(keyNavigatorBehavior);

        this.bg.compile();
        this.universe.addBranchGraph(this.bg);

        // Heraus gezoomt
        TransformGroup VpTG = this.universe.getViewingPlatform().getViewPlatformTransform();

        float Zcamera = 12; //put the camera 12 meters back
        Transform3D Trfcamera = new Transform3D();
        Trfcamera.setTranslation(new Vector3f(0.0f, 0.0f, Zcamera));  
        VpTG.setTransform( Trfcamera );
    }    

    public int getWidth() {
        return this.width;
    }

    public int getHeight() {
        return this.height;
    }

    public int getDepth() {
        return this.depth;
    }

    public float getSize() {
        return this.size;
    }

    public Color getColor() {
        return LedCube.colors.get(this.selectedColor);
    }

    public Color getDarkerColor() {
        return this.getColor().darker().darker().darker();
    }

    public void changeColor() {
        this.selectedColor ++;
        if (this.selectedColor > LedCube.colors.size()) {
            this.selectedColor = 0;
        }

        this.setChanged();
        this.notifyObservers(new ActionEvent(this.getColor(), ActionEvent.ACTION_FIRST, "color"));
    }

    public void changeEnable(int layer, int row, int col, boolean enabled) {
    	// layer: x
    	// row  : y
    	// col  : z
        int[] params = new int[4];
        params[0] = (enabled ? 1 : 0);
        params[1] = layer;   
        params[2] = row;
        params[3] = col;

        this.setChanged();
        this.notifyObservers(new TextEvent(params, ActionEvent.ACTION_FIRST));
    }
    
    public static void main(String[] args) {
        new LedCube(5, 5, 10, 0.1f);
    } 
}

